var s = "𠮷";

s.length // 2
console.log(s.charAt(0)) // ''
console.log(s.charAt(1)) // ''
console.log(s.charCodeAt(0) )// 55362
console.log(s.charCodeAt(1)) // 57271

/*
上面代码中，汉字“𠮷”（注意，这个字不是“吉祥”的“吉”）的码点是0x20BB7，
UTF-16 编码为0xD842 0xDFB7（十进制为55362 57271），需要4个字节储存。
对于这种4个字节的字符，JavaScript 不能正确处理，字符串长度会误判为2，
而且charAt方法无法读取整个字符，charCodeAt方法只能分别返回前两个字节和后两个字节的值。
*/
let ss = '𠮷a';

console.log(ss.codePointAt(0) )// 134071
console.log(ss.codePointAt(1)) // 57271

console.log(ss.codePointAt(2)) // 97

/*
codePointAt方法的参数，是字符在字符串中的位置（从 0 开始）。
上面代码中，JavaScript 将“𠮷a”视为三个字符，
codePointAt 方法在第一个字符上，正确地识别了“𠮷”，
返回了它的十进制码点 134071（即十六进制的20BB7）。
在第二个字符（即“𠮷”的后两个字节）和第三个字符“a”上，
codePointAt方法的结果与charCodeAt方法相同。

总之，codePointAt方法会正确返回 32 位的 UTF-16 字符的码点。
对于那些两个字节储存的常规字符，它的返回结果与charCodeAt方法相同。

codePointAt方法返回的是码点的十进制值，如果想要十六进制的值，
可以使用toString方法转换一下。
*/
console.log(s.codePointAt(0).toString(16));
console.log(s.codePointAt(1).toString(16))

for (let ch of s) {
    console.log(ch.codePointAt(0).toString(16));
  }
//   你可能注意到了，codePointAt方法的参数，仍然是不正确的。
// 比如，上面代码中，字符a在字符串s的正确位置序号应该是 1，
// 但是必须向codePointAt方法传入 2。
// 解决这个问题的一个办法是使用for...of循环，因为它会正确识别 32 位的 UTF-16 字符。
function is32Bit(c) {
    return c.codePointAt(0) > 0xFFFF;
  }
  
console.log(is32Bit("𠮷")) // true
console.log(is32Bit("a")) // false